package dao

import (
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"context"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"sale-admin/config/mysql"

	"sale-admin/internal/models"
)

type GoodsLogRepo struct {
	db *gorm.DB
}

func getCommonConn(in any) *gorm.DB {
	if db, ok := in.(*gorm.DB); ok {
		return db
	}
	ctx := in.(context.Context)

	return mysql.NewDB().WithContext(ctx)
}

func NewGoodsLogRepo(in any) *GoodsLogRepo {
	return &GoodsLogRepo{db: getCommonConn(in)}
}

type IGoodsLogFilter interface {
	fmtFilter(ctx context.Context, db *gorm.DB) *gorm.DB
}

var _ IGoodsLogFilter = (*GoodsLogFilter)(nil)

type GoodsLogFilter struct {
	//todo 添加过滤字段
	GoodsID string
}

func (p *GoodsLogFilter) fmtFilter(ctx context.Context, db *gorm.DB) *gorm.DB {
	//todo 添加条件
	return db
}

type PayNotifyFilter_2 struct {
	//todo 添加过滤字段
}

func (p *PayNotifyFilter_2) fmtFilter(ctx context.Context, db *gorm.DB) *gorm.DB {
	//todo 添加条件
	return db
}

func (p GoodsLogRepo) fmtFilter(ctx context.Context, f IGoodsLogFilter) *gorm.DB {
	db := p.db.WithContext(ctx)
	db = f.fmtFilter(ctx, db)
	return db
}

func (p GoodsLogRepo) Insert(ctx context.Context, data *models.MaGoodsInfoLog) error {
	result := p.db.WithContext(ctx).Create(data)
	return result.Error
}

func (p GoodsLogRepo) FindOneByFilter(ctx context.Context, f *GoodsLogFilter) (*models.MaGoodsInfoLog, error) {
	var result models.MaGoodsInfoLog
	db := p.fmtFilter(ctx, f)
	err := db.First(&result).Error
	if err != nil {
		return nil, err
	}
	return &result, nil
}
func (p GoodsLogRepo) FindByFilter(ctx context.Context, f *GoodsLogFilter, page *helper.PageInfo) ([]*models.MaGoodsInfoLog, error) {
	var results []*models.MaGoodsInfoLog
	db := p.fmtFilter(ctx, f).Model(&models.MaGoodsInfoLog{})
	db = page.ToGorm(db)
	err := db.Find(&results).Error
	if err != nil {
		return nil, err
	}
	return results, nil
}

func (p GoodsLogRepo) CountByFilter(ctx context.Context, f *GoodsLogFilter) (size int64, err error) {
	db := p.fmtFilter(ctx, f).Model(&models.MaGoodsInfoLog{})
	err = db.Count(&size).Error
	return size, err
}

func (p GoodsLogRepo) Update(ctx context.Context, data *models.MaGoodsInfoLog) error {
	err := p.db.WithContext(ctx).Where("id = ?", data.ID).Save(data).Error
	return err
}

func (p GoodsLogRepo) DeleteByFilter(ctx context.Context, f *GoodsLogFilter) error {
	db := p.fmtFilter(ctx, f)
	err := db.Delete(&models.MaGoodsInfoLog{}).Error
	return err
}

func (p GoodsLogRepo) Delete(ctx context.Context, id int64) error {
	err := p.db.WithContext(ctx).Where("id = ?", id).Delete(&models.MaGoodsInfoLog{}).Error
	return err
}
func (p GoodsLogRepo) FindOne(ctx context.Context, id int64) (*models.MaGoodsInfoLog, error) {
	var result models.MaGoodsInfoLog
	err := p.db.WithContext(ctx).Where("id = ?", id).First(&result).Error
	if err != nil {
		return nil, err
	}
	return &result, nil
}

// 批量插入 LightStrategyDevice 记录
func (p GoodsLogRepo) MultiInsert(ctx context.Context, data []*models.MaGoodsInfoLog) error {
	err := p.db.WithContext(ctx).Clauses(clause.OnConflict{UpdateAll: true}).Model(&models.MaGoodsInfoLog{}).Create(data).Error
	return err
}

func (p GoodsLogRepo) ListByFilter(ctx context.Context, f *GoodsLogFilter, page *helper.PageInfo) ([]*models.MaGoodsInfoLog, int64, error) {
	list, err := p.FindByFilter(ctx, f, page)
	if err != nil {
		return nil, 0, err
	}

	size, err := p.CountByFilter(ctx, f)
	if err != nil {
		return nil, 0, err
	}

	return list, size, nil
}

// 采用泛型方案

type IGoodsLogFilterV2 interface {
	fmtFilter(ctx context.Context, db *gorm.DB) *gorm.DB
	Table() interface{}
}

var _ IGoodsLogFilterV2 = (*GoodsLogFilterJoin)(nil)

type GoodsLogFilterJoin struct {
	table models.MaGoodsInfoLog
	//todo 添加过滤字段
	GoodsID string
}

func (p *GoodsLogFilterJoin) fmtFilter(ctx context.Context, db *gorm.DB) *gorm.DB {
	//todo 添加条件
	if p.GoodsID != "" {
		db = db.WithContext(ctx)
		db = db.Where("goods_id = ?", p.GoodsID)
		//db = db.Joins("LEFT JOIN ma_goods_info ON ma_goods_info_log.goods_id = ma_goods_info.id").
		//	Where("ma_goods_info.goods_id = ?", p.GoodsID)

		// 当 FieldName 为 ExpressFeeTemplate 时，连接 express_fee_setting 表
		// 修复 JOIN 条件：只在 field_name = 'ExpressFeeTemplate' 时才进行关联
		db = db.Joins("LEFT JOIN express_fee_setting AS old_express_fee_setting ON ma_goods_info_log.field_name = 'ExpressFeeTemplate' AND ma_goods_info_log.old_value = old_express_fee_setting.id")
		db = db.Joins("LEFT JOIN express_fee_setting AS new_express_fee_setting ON ma_goods_info_log.field_name = 'ExpressFeeTemplate' AND ma_goods_info_log.new_value = new_express_fee_setting.id")

		// 明确选择所有需要的字段以确保正确的映射
		db = db.Select(`
		ma_goods_info_log.*,
		old_express_fee_setting.id as old_id,
		old_express_fee_setting.name as old_name,
		old_express_fee_setting.created_at as old_created_at,
		old_express_fee_setting.updated_at as old_updated_at,
		new_express_fee_setting.id as new_id,
		new_express_fee_setting.name as new_name,
		new_express_fee_setting.created_at as new_created_at,
		new_express_fee_setting.updated_at as new_updated_at
	`)

	}

	return db

}

func (p *GoodsLogFilterJoin) Table() interface{} {
	return &p.table
}

func (p GoodsLogRepo) FindByFilterV2(ctx context.Context, f IGoodsLogFilterV2, page *helper.PageInfo) ([]*models.MaGoodsInfoLogJoinType, error) {
	var results []*models.MaGoodsInfoLogJoinType
	db := p.fmtFilter(ctx, f).Model(f.Table())
	db = page.ToGorm(db)
	err := db.Find(&results).Error
	if err != nil {
		logx.Error(ctx, "List err: %v", logx.Any("err", err))
		return nil, err
	}
	return results, nil
}

func (p GoodsLogRepo) CountByFilterV2(ctx context.Context, f IGoodsLogFilterV2) (size int64, err error) {
	db := p.fmtFilter(ctx, f).Model(&models.MaGoodsInfoLog{})
	err = db.Count(&size).Error
	return size, err
}

func (p GoodsLogRepo) ListByFilterV2(ctx context.Context, f IGoodsLogFilterV2, page *helper.PageInfo) ([]*models.MaGoodsInfoLogJoinType, int64, error) {
	list, err := p.FindByFilterV2(ctx, f, page)
	if err != nil {
		return nil, 0, err
	}

	size, err := p.CountByFilterV2(ctx, f)
	if err != nil {
		return nil, 0, err
	}

	return list, size, nil
}
